home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Washington_1988 / DevCon88.3 / CTipsAndTricks / Rstartup.asm < prev    next >
Encoding:
Assembly Source File  |  1992-08-27  |  20.3 KB  |  755 lines

  1. *------ startup.asm  v 34.12   Copyright 1988 Commodore-Amiga, Inc.
  2. *------
  3. *------ Conditional assembly flags
  4. *------ ASTART:   1=Standard Globals Defined    0=Reentrant Only
  5. *------ WINDOW:   1=AppWindow for WB startup    0=No AppWindow code
  6. *------ XNIL:     1=Remove startup NIL: init    0=Default Nil: WB Output
  7. *------ NARGS:    1=Argv[0] only                0=Normal cmd line arg parse
  8. *------ DEBUG:    1=Set up old statics for Wack 0=No extra statics
  9. *------ QARG:     1=No argv                 0=Passes argc,argv
  10.  
  11. * Include the appropriate .i file to set the flags
  12.  
  13.     INCLUDE "astartup.i"
  14.  
  15. * Flags for  [A]start  AWstart  Rstart  RWstart  RXstart  QStart
  16. * ASTART         1        1       0        0        0       0
  17. * WINDOW         0        1       0        1        0       0
  18. * XNIL           0        0       0        0        1       1
  19. * NARGS          0        0       0        0        0       0
  20. * DEBUG          0        0       0        0        0       0
  21. * QARG           0        0       0        0        0       1
  22.  
  23. ;------   Flag WB output initialization
  24. WBOUT     SET   (ASTART!WINDOW!(1-XNIL))
  25.  
  26. ************************************************************************
  27. *
  28. *   startup.asm --- Reentrant C Program Startup/Exit (CLI and WB)
  29. *                   Made reentrant by C. Scheppner
  30. *            Optimized by Kodiak Burns
  31. *                   v34.12  07/25/88
  32. *
  33. *   Copyright (c) 1988 Commodore-Amiga, Inc.
  34. *
  35. *   Title to this software and all copies thereof remain vested in the
  36. *   authors indicated in the above copyright notice.  The object version
  37. *   of this code may be used in software for Commodore Amiga computers.
  38. *   All other rights are reserved.
  39. *
  40. *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE
  41. *   ACCURACY, RELIABILITY, PERFORMANCE OR OPERATION OF THIS SOFTWARE,
  42. *   AND ALL SUCH USE IS AT YOUR OWN RISK.  NEITHER COMMODORE NOR THE
  43. *   AUTHORS ASSUME ANY RESPONSIBILITY OR LIABILITY WHATSOEVER WITH
  44. *   RESPECT TO YOUR USE OF THIS SOFTWARE.
  45. *
  46. *
  47. *   RSTARTUP.ASM
  48. *
  49. *      This startup dynamically allocates a structure which includes
  50. *   the argv buffers.  If you use this startup, your code must return
  51. *   to this startup when it exits.  Use exit(n) or final curly brace
  52. *   (rts) to return here.  Do not use AmigaDOS Exit() function.
  53. *   Due to this dynamic allocation and some code consolidation, this
  54. *   startup can make executables several hundred bytes smaller.
  55. *
  56. *       Because a static initialSP variable can not be used, this
  57. *   code depends on the fact that AmigaDOS places the address of
  58. *   the top of our stack in SP and proc->pr_ReturnAddr right before
  59. *   JSR'ing to us.  This code uses pr_ReturnAddr when restoring SP.
  60. *
  61. *       Most versions of startup will initialize a Workbench process's
  62. *   input and output streams (and stdio globals if present) to NIL:
  63. *   if no other form of Workbench output (like WINDOW) is provided.
  64. *   This should help prevent crashes if a user puts an icon on a CLI
  65. *   program, and will also protect against careless stdio debugging
  66. *   or error messages left in a Workbench program.  The code for
  67. *   initializing Workbench IO streams only be removed by assembling
  68. *   startup with ASTART and WINDOW set to 0, and XNIL set to 1.
  69. *
  70. *
  71. *   Some startups which can be conditionally assembled:
  72. *
  73. *      1. Standard Astartup for non-reentrant code
  74. *      2. Reentrant Rstartup (no unshareable globals)
  75. *      3. Smaller reentrant-only RXstartup (no NIL: WB init code)
  76. *      4. Standard AWstartup (WB output window) for non-reentrant code
  77. *      5. Reentrant RWstartup (WB output window, no unshareable globals)
  78. *      6. Smallest Qstartup  (No argv - argv is ptr to NULL string)
  79. *
  80. *
  81. *   Explanation of conditional assembly flags:
  82. *
  83. *      ASTART (ASTART SET 1) startups will set up and XDEF the
  84. *   global variables _stdin, _stdout, _stderr, _errno and  _WBenchMsg.
  85. *   These startups can be used as smaller replacements for startups
  86. *   like (A)startup.obj and TWstartup.obj.  Startups with ASTART
  87. *   would generally be used for non-reentrant programs, although the
  88. *   startup code itself is still reentrant if the globals are not
  89. *   referenced.
  90. *      Reentrant (ASTART SET 0) startups will NOT set up or
  91. *   XDEF the stdio and WBenchMsg globals.  This not only makes the
  92. *   startup slightly smaller, but also lets you know if your code
  93. *   is referencing these non-reentrant globals (you will get an
  94. *   unresolved external reference when you link).  Programs
  95. *   get their input and output handles from Input() and Output(),
  96. *   and the WBenchMsg is passed in argv on Workbench startup.
  97. *
  98. *      WINDOW (WINDOW SET 1) startups use an XREF'd CON: string
  99. *   named AppWindow, defined in your application, to open a stdio
  100. *   console window when your application is started from Workbench.
  101. *   For non-reentrant programs, this window can be used for normal
  102. *   stdio (printf, getchar, etc).  For reentrant programs the window
  103. *   is Input() and Output().  WINDOW is useful when adding Workbench
  104. *   capability to a stdio application, and also for debugging other
  105. *   Workbench applications.  To insure that applications requiring
  106. *   a window startup are linked with a window startup, the label
  107. *   _NeedWStartup can be externed and referenced in the application
  108. *   so that a linker error will occur if linked with a standard
  109. *   startup.
  110. *
  111. *       example:   /* Optional safety reference to NeedWStartup */
  112. *                    extern UBYTE  NeedWStartup;
  113. *                    UBYTE  *HaveWStartup = &NeedWStartup;
  114. *                  /* Required window specification */
  115. *                    char AppWindow[] = "CON:30/30/200/150/MyProgram";
  116. *                    ( OR  char AppWindow[] = "\0";  for no window )
  117. *
  118. *
  119. *      XNIL (XNIL SET 1) allows the creation of a smaller startup
  120. *   by removing the code that initializes a Workbench process's
  121. *   output streams to NIL:.  This flag can only remove the code
  122. *   if it is not required for ASTART or WINDOW.
  123. *
  124. *      NARGS (NARGS SET 1) removes the code used to parse command line
  125. *   arguments.  The command name is still passed to _main as argv[0].
  126. *   This option can take about 120 bytes off the size of any program that
  127. *   does not use command line args.
  128. *
  129. *      DEBUG (DEBUG SET 1) will cause the old startup.asm statics
  130. *   initialSP, dosCmdLen and dosCmdBuf to be defined and initialized
  131. *   by the startup code, for use as debugging symbols when using Wack.
  132. *
  133. *      QARG (QARG SET TO 1) will bypass all argument parsing.  A CLI
  134. *   startup is passed argc == 1, and a Workbench startup is passed
  135. *   argc == 0.  Argv[0] will be a pointer to a NULL string rather than
  136. *   a pointer to the command name.  This option creates a very small
  137. *   startup with no sVar structure allocation, and therefore must be used
  138. *   with XNIL (it is incompatible with default or AWindow output options).
  139. *
  140. *
  141. *   RULES FOR REENTRANT CODE
  142. *
  143. *      - Make no direct or indirect (printf, etc) references to the
  144. *        globals _stdin, _stdout, _stderr, _errno, or _WBenchMsg.
  145. *
  146. *      - For stdio use either special versions of printf and getchar
  147. *        that use Input() and Output() rather than _stdin and _stdout,
  148. *        or use fprintf and fgetc with Input() and Output() file handles.
  149. *
  150. *      - Workbench applications must get the pointer to the WBenchMsg
  151. *        from argv rather than from a global extern WBenchMsg.
  152. *
  153. *      - Use no global or static variables within your code.  Instead,
  154. *        put all former globals in a dynamically allocated structure, and
  155. *        pass around a pointer to that structure.  The only acceptable
  156. *        globals are constants (message strings, etc) and global copies
  157. *        of Library Bases to resolve Amiga.lib references.  Your code
  158. *        must return all OpenLibrary's into non-global variables,
  159. *        copy the result to the global library base only if successful,
  160. *        and use the non-globals when deciding whether to Close any
  161. *        opened libraries.  
  162. *
  163. ************************************************************************
  164.  
  165.  
  166. ******* Included Files *************************************************
  167.  
  168.     INCLUDE    "exec/types.i"
  169.     INCLUDE    "exec/alerts.i"
  170.     INCLUDE    "exec/memory.i"
  171.     INCLUDE    "libraries/dos.i"
  172.     INCLUDE    "libraries/dosextens.i"
  173.     INCLUDE    "workbench/startup.i"
  174.  
  175.  
  176. ******* Macros *********************************************************
  177.  
  178. xlib    macro
  179.     xref    _LVO\1
  180.     endm
  181.  
  182. callsys    macro
  183.     CALLLIB    _LVO\1
  184.     endm
  185.  
  186. ******* Imported *******************************************************
  187.  
  188. ABSEXECBASE    EQU    4
  189.  
  190.     xref    _main        ; C code entry point
  191.  
  192.     IFGT    WINDOW
  193.     xref    _AppWindow    ; CON: spec in application for WB stdio window
  194.     xdef    _NeedWStartup    ; May be externed and referenced in application
  195.     ENDC    WINDOW
  196.  
  197.     xlib    Alert
  198.     xlib    AllocMem
  199.     xlib    FindTask
  200.     xlib    Forbid
  201.     xlib    FreeMem
  202.     xlib    GetMsg
  203.     xlib    OpenLibrary
  204.     xlib    CloseLibrary
  205.     xlib    ReplyMsg
  206.     xlib    Wait
  207.     xlib    WaitPort
  208.  
  209.     xlib    CurrentDir
  210.     xlib    Open
  211.     xlib    Close
  212.     xlib    Input
  213.     xlib    Output
  214.  
  215. ******* Exported *******************************************************
  216.  
  217. *----- These globals are set up for standard startup code only
  218.     IFGT    ASTART
  219.     xdef    _stdin
  220.     xdef    _stdout
  221.     xdef    _stderr
  222.     xdef    _errno
  223.     xdef    _WBenchMsg
  224.     ENDC    ASTART
  225.  
  226. *----- These globals available to normal and reentrant code
  227.  
  228.     xdef    _SysBase
  229.     xdef    _DOSBase
  230.     xdef    _exit        ; standard C exit function
  231.  
  232.  
  233. ***** Startup Variables structure **********************************
  234.  
  235.     IFEQ    QARG
  236. ARGVSLOTS    EQU    32
  237.  
  238.  STRUCTURE  SVar,0
  239.     LONG    sv_WbOutput
  240.     STRUCT  sv_argvArray,ARGVSLOTS*4
  241.     STRUCT  sv_argvBuffer,256
  242.     LABEL   SV_SIZEOF
  243.     ENDC    QARG
  244.  
  245. ************************************************************************
  246. *
  247. *   Standard Program Entry Point
  248. *
  249. ************************************************************************
  250. *
  251. *    Entered with
  252. *        d0  dosCmdLen
  253. *        a0  dosCmdBuf
  254. *    Any registers (except sp) are allowed to be modified
  255. *
  256. *    Calls
  257. *        main (argc, argv)
  258. *        int   argc;
  259. *        char *argv[]; 
  260. *
  261. *        For Workbench startup, argc=0, argv=WBenchMsg
  262. *
  263. ************************************************************************
  264. startup:
  265.     IFGT    DEBUG
  266.         move.l    sp,initialSP
  267.         move.l    d0,dosCmdLen
  268.         move.l    a0,dosCmdBuf
  269.     ENDC    DEBUG
  270.  
  271.     IFEQ    QARG
  272.         move.l    d0,d2
  273.         move.l    a0,a2
  274.     ENDC    QARG
  275.  
  276.     ;------ get Exec library base pointer
  277.         movea.l    ABSEXECBASE,a6
  278.         move.l    a6,_SysBase
  279.  
  280.     ;------ get the address of our task
  281.         suba.l    a1,a1        ; clear a1
  282.         callsys    FindTask
  283.         move.l    d0,a4        ; keep task address in a4
  284.  
  285.     ;------ get DOS library base pointer
  286.         moveq    #0,d0
  287.         lea    DOSName(pc),A1    ; dos.library
  288.         callsys    OpenLibrary
  289.  
  290.         tst.l   d0
  291.         beq    alertDOS    ; fail on null with alert
  292.         move.l    d0,_DOSBase    ; Else set the global
  293.     
  294.  
  295.     IFEQ    QARG
  296.     ;------ alloc the argument structure
  297.         move.l    #SV_SIZEOF,d0
  298.         move.l    #(MEMF_PUBLIC!MEMF_CLEAR),d1
  299.         callsys    AllocMem
  300.         tst.l    d0
  301.         beq    alertMem    ; fail on null with alert
  302.         move.l    d0,-(sp)    ; save sVar ptr on stack
  303.         move.l    d0,a5        ; sVar ptr to a5
  304.     ENDC    QARG
  305.     IFGT    QARG
  306.         clr.l    -(sp)
  307.     ENDC    QARG
  308.  
  309.         clr.l    -(sp)        ; reserve space for WBenchMsg if any
  310.  
  311.     ;------ branch to Workbench startup code if not a CLI process
  312.         move.l    pr_CLI(A4),d0
  313.         beq    fromWorkbench
  314.  
  315. ;=======================================================================
  316. ;====== CLI Startup Code ===============================================
  317. ;=======================================================================
  318. ;    d0  process CLI BPTR (passed in), then temporary
  319. ;    d2  dos command length (passed in)
  320. ;    d3  argument count
  321. ;    a0  temporary
  322. ;    a1  argv buffer
  323. ;    a2  dos command buffer (passed in)
  324. ;    a3  argv array
  325. ;    a4  Task (passed in)
  326. ;    a5  SVar structure if not QARG (passed in)
  327. ;    a6  AbsExecBase (passed in)
  328. ;    sp  WBenchMsg (still 0), sVar or 0, then RetAddr (passed in)
  329. ;    sp  argc, argv, WBenchMsg, sVar or 0,RetAddr (at bra domain)
  330.  
  331.     IFEQ    QARG
  332.     ;------ find command name
  333.         lsl.l    #2,d0        ; pr_CLI bcpl pointer conversion
  334.         move.l    d0,a0
  335.         move.l    cli_CommandName(a0),d0
  336.         lsl.l    #2,d0        ; bcpl pointer conversion
  337.  
  338.         ;-- start argv array
  339.         lea    sv_argvBuffer(a5),a1
  340.         lea    sv_argvArray(a5),a3
  341.  
  342.         ;-- copy command name
  343.         move.l    d0,a0
  344.         moveq.l    #0,d0
  345.         move.b    (a0)+,d0    ; size of command name
  346.         clr.b    0(a0,d0.l)    ; terminate the command name
  347.         move.l    a0,(a3)+
  348.         moveq    #1,d3        ; start counting arguments
  349.  
  350.     IFEQ    NARGS    
  351.     ;------ null terminate the arguments, eat trailing control characters
  352.         lea    0(a2,d2.l),a0
  353. stripjunk:
  354.         cmp.b    #' ',-(a0)
  355.         dbhi    d2,stripjunk
  356.  
  357.         clr.b    1(a0)
  358.  
  359.     ;------ start gathering arguments into buffer
  360. newarg:
  361.         ;-- skip spaces
  362.         move.b    (a2)+,d1
  363.         beq.s    parmExit
  364.         cmp.b    #' ',d1
  365.         beq.s    newarg
  366.         cmp.b    #9,d1        ; tab
  367.         beq.s    newarg
  368.  
  369.         ;-- check for argument count overflow
  370.         cmp.w    #ARGVSLOTS-1,d3
  371.         beq.s    parmExit
  372.  
  373.         ;-- push address of the next parameter
  374.         move.l    a1,(a3)+
  375.         addq.w    #1,d3
  376.  
  377.         ;-- process quotes
  378.         cmp.b    #'"',d1
  379.         beq.s    doquote
  380.  
  381.         ;-- copy the parameter in
  382.         move.b    d1,(a1)+
  383.  
  384. nextchar:
  385.         ;------ null termination check
  386.         move.b    (a2)+,d1
  387.         beq.s    parmExit
  388.         cmp.b    #' ',d1
  389.         beq.s    endarg
  390.  
  391.         move.b    d1,(a1)+
  392.         bra.s    nextchar
  393.  
  394. endarg:
  395.         clr.b    (a1)+
  396.         bra.s    newarg
  397.  
  398. doquote:
  399.     ;------ process quoted strings
  400.         move.b    (a2)+,d1
  401.         beq.s    parmExit
  402.         cmp.b    #'"',d1
  403.         beq.s    endarg
  404.  
  405.         ;-- '*' is the BCPL escape character
  406.         cmp.b    #'*',d1
  407.         bne.s    addquotechar
  408.  
  409.         move.b    (a2)+,d1
  410.         move.b    d1,d2
  411.         and.b    #$df,d2        ;d2 is temp toupper'd d1
  412.  
  413.         cmp.b    #'N',d2        ;check for dos newline char
  414.         bne.s    checkEscape
  415.  
  416.         ;--    got a *N -- turn into a newline
  417.         moveq    #10,d1
  418.         bra.s    addquotechar
  419.  
  420. checkEscape:
  421.         cmp.b    #'E',d2
  422.         bne.s    addquotechar
  423.  
  424.         ;--    got a *E -- turn into a escape
  425.         moveq    #27,d1
  426.  
  427. addquotechar:
  428.         move.b    d1,(a1)+
  429.         bra.s    doquote
  430.  
  431. parmExit:
  432.     ;------ all done -- null terminate the arguments
  433.         clr.b    (a1)
  434.         clr.l    (a3)
  435.     ENDC NARGS
  436.  
  437.         pea    sv_argvArray(a5) ; argv
  438.         move.l    d3,-(sp)     ; argc
  439.     ENDC    QARG
  440.  
  441.     IFGT    QARG
  442.         pea    nullArgV(pc)    ; pointer to pointer to null string
  443.         pea    1        ; only one pointer
  444.     ENDC
  445.  
  446.     IFGT    ASTART
  447.         movea.l    _DOSBase,a6
  448.     ;------ get standard input handle:
  449.         callsys    Input
  450.         move.l    d0,_stdin
  451.  
  452.     ;------ get standard output handle:
  453.         callsys    Output
  454.         move.l    d0,_stdout
  455.         move.l    d0,_stderr
  456.         movea.l    ABSEXECBASE,a6
  457.     ENDC ASTART
  458.  
  459.         bra    domain
  460.  
  461.  
  462. ;=======================================================================
  463. ;====== Workbench Startup Code =========================================
  464. ;=======================================================================
  465. ;    a2  WBenchMsg
  466. ;    a4  Task (passed in)
  467. ;    a5  SVar structure if not QARG (passed in)
  468. ;    a6  AbsExecBase (passed in)
  469. ;    sp  WBenchMsg (still 0), sVar or 0, then RetAddr (passed in)
  470. ;    sp  argc=0,argv=WBenchMsg,WBenchMsg,sVar or 0,RetAddr (at domain)
  471.  
  472. fromWorkbench:
  473.     ;------ get the startup message that workbench will send to us.
  474.     ;    must get this message before doing any DOS calls
  475.         bsr.s   getWbMsg
  476.  
  477.     ;------ save the message so we can return it later
  478.         move.l    d0,(sp)
  479.     IFGT    ASTART
  480.         move.l    d0,_WBenchMsg
  481.     ENDC    ASTART
  482.  
  483.     ;------ push the message on the stack for wbmain (as argv)
  484.         move.l    d0,-(sp)
  485.         clr.l    -(sp)        ; indicate run from Workbench (argc=0)
  486.  
  487.     IFNE    (1-QARG)+WBOUT
  488.     ;------ put DOSBase in a6 for next few calls
  489.         move.l    _DOSBase,a6
  490.     ENDC    (1-QARG)+WBOUT
  491.  
  492.     IFEQ    QARG
  493.     ;------ get the first argument
  494.         move.l    d0,a2
  495.         move.l    sm_ArgList(a2),d0
  496.         beq.s    doCons
  497.  
  498.     ;------ and set the current directory to the same directory
  499.         move.l    d0,a0
  500.         move.l    wa_Lock(a0),d1
  501.         callsys    CurrentDir
  502. doCons: 
  503.     ENDC    QARG
  504.  
  505.     IFGT    WBOUT
  506.  
  507.     ;------ Open NIL: or AppWindow for WB Input()/Output() handle
  508.     ;    Also for possible initialization of stdio globals
  509.     ;    Stdio used to be initialized to -1
  510.  
  511.       
  512.     IFGT    WINDOW
  513.     ;------ Get AppWindow defined in application
  514.         lea    _AppWindow,a0
  515.         cmp.b    #0,(a0)
  516.         bne.s    doOpen        ; Open if not null string
  517.     ENDC    WINDOW
  518.  
  519.     ;------ Open NIL: if no window provided
  520.     lea    NilName(PC),a0
  521.  
  522. doOpen:
  523.     ;------ Open up the file whose name is in a0
  524.     ;    DOSBase still in a6
  525.         move.l    a0,d1
  526.         move.l    #MODE_OLDFILE,d2 
  527.         callsys    Open 
  528.     ;------ d0 now contains handle for Workbench Output
  529.     ;------ save handle for closing on exit
  530.         move.l    d0,sv_WbOutput(a5)
  531.         bne.s    gotOpen
  532.         moveq.l #RETURN_FAIL,d2
  533.         bra     exit2
  534. gotOpen:
  535.     IFGT ASTART
  536.     ;------ set the C input and output descriptors 
  537.         move.l    d0,_stdin
  538.         move.l    d0,_stdout
  539.         move.l    d0,_stderr
  540.     ENDC ASTART
  541.  
  542.     ;------ set the console task (so Open( "*", mode ) will work 
  543.     ;    task pointer still in A4
  544.         move.l    d0,pr_CIS(A4)
  545.         move.l    d0,pr_COS(A4)
  546.         lsl.l    #2,d0 
  547.         move.l    d0,a0 
  548.         move.l    fh_Type(a0),d0
  549.         beq.s    noConTask
  550.         move.l    d0,pr_ConsoleTask(A4)
  551. noConTask:
  552.     ENDC WBOUT
  553.  
  554.     ;------ Fall though to common WB/CLI code
  555.  
  556.  
  557. ****************************************************
  558. **                                                **
  559. ** This code now used by both CLI and WB startup  **
  560. **                                                **
  561. ****************************************************
  562.  
  563. domain:
  564.         jsr    _main
  565.     ;------ main didn't use exit(n) so provide success return code
  566.         moveq.l    #RETURN_OK,d2
  567.         bra.s    exit2
  568.  
  569.  
  570. ****************************************************
  571. **                                                **
  572. **    subroutines here to allow short branches    **
  573. **                                                **
  574. ****************************************************
  575.  
  576. getWbMsg:
  577.     ;------ a6 = ExecBase
  578.         lea    pr_MsgPort(A4),a0    ; our process base
  579.         callsys    WaitPort
  580.         lea    pr_MsgPort(A4),a0    ; our process base
  581.         callsys    GetMsg
  582.         rts
  583.  
  584. ****************************************************
  585.  
  586. alertDOS:
  587.     ;------ do recoverable alert for no DOS and exit
  588.         ALERT    (AG_OpenLib!AO_DOSLib)
  589.     
  590.     ;------ do recoverable alert for no memory and exit
  591.     ;------ If we got this far, DOS is open, so close it
  592.     IFEQ QARG
  593.         bra.s    failExit
  594. alertMem:
  595.         movea.l _DOSBase,a1
  596.         callsys CloseLibrary    
  597.         ALERT    AG_NoMemory
  598.     ENDC QARG
  599. failExit:
  600.         tst.l   pr_CLI(a4)
  601.         bne.s   fail2
  602.         bsr.s    getWbMsg
  603.         movea.l d0,a2
  604.         bsr.s    repWbMsg
  605. fail2:
  606.         moveq.l    #RETURN_FAIL,d0
  607.         rts
  608.  
  609. ****************************************************
  610.  
  611. repWbMsg:
  612.     ;------ return the startup message to our parent
  613.     ;       a6 = ExecBase (passed)
  614.     ;    a2 = WBenchMsg (passed)
  615.     ;    we forbid so workbench can't UnLoadSeg() us before we are done
  616.         callsys    Forbid
  617.         move.l    a2,a1
  618.         callsys    ReplyMsg
  619.         rts
  620.  
  621.  
  622. *******************************************************
  623. **                                                   **
  624. **  C Program exit() Function, return code on stack  **
  625. **                                                   **
  626. **  pr_ReturnAddr points to our RTS addr on stack    **
  627. **  and we use this to calculate our stack ptr:      ** 
  628. **                                                   **
  629. **      SP ->   WBenchMsg or 0 (CLI)                 **
  630. **              sVar ptr or 0 (QARG)                 **
  631. **              Address for RTS to DOS               **
  632. **                                                   **
  633. *******************************************************
  634.  
  635. _exit:
  636.         move.l    4(sp),d2    ; exit(n) return code to d2
  637.  
  638. exit2:                    ;exit code in d2
  639.     ;------ restore initial stack ptr
  640.         ;-- FindTask
  641.         movea.l    ABSEXECBASE,a6
  642.         suba.l    a1,a1
  643.         callsys    FindTask
  644.         ;-- get SP as it was prior to DOS's jsr to us
  645.         move.l    d0,a4
  646.         move.l    pr_ReturnAddr(a4),a5
  647.         ;-- subtract 4 for return address, 4 for SVar, 4 for WBenchMsg
  648.         suba.w    #12,a5
  649.  
  650.         ;-- restore sp
  651.         move.l    a5,sp
  652.     
  653.         ;-- recover WBenchMsg
  654.         move.l    (sp)+,a2
  655.         ;-- recover SVar
  656.         move.l    (sp)+,a5
  657.  
  658.  
  659.     IFGT    WBOUT
  660.     ;------ Close any WbOutput file before closing dos.library
  661.         move.l    sv_WbOutput(a5),d1
  662.         beq.s    noWbOut
  663.         move.l    _DOSBase,a6
  664.         callsys Close
  665. noWbOut:
  666.     ;------ Restore a6 = ExecBase
  667.         movea.l ABSEXECBASE,a6
  668.     ENDC    WBOUT
  669.  
  670.     ;------ Close DOS library, if we got here it was opened
  671.     ;    SysBase still in a6
  672.         movea.l    _DOSBase,a1
  673.         callsys    CloseLibrary
  674.  
  675.     ;------ if we ran from CLI, skip workbench reply
  676. checkWB:
  677.         move.l    a2,d0
  678.         beq.s    deallocSV
  679.  
  680.         bsr.s    repWbMsg
  681.  
  682. deallocSV:
  683.     IFEQ    QARG
  684.     ;------ deallocate the SVar structure
  685.         move.l    a5,a1
  686.         move.l    #SV_SIZEOF,d0
  687.         callsys FreeMem
  688.     ENDC    QARG
  689.  
  690.     ;------ this rts sends us back to DOS:
  691.         move.l    d2,d0
  692.         rts
  693.  
  694.  
  695. **********************************************************************
  696.  
  697. ;----- PC relative data
  698.  
  699. DOSName        DOSNAME
  700. NilName        dc.b    'NIL:',0
  701.     IFGT    QARG
  702. nullArgV    dc.l    nullArg
  703. nullArg        dc.l    0        ; "" & the null entry after nullArgV
  704.     ENDC
  705.  
  706. **********************************************************************
  707.  
  708.    DATA
  709.  
  710. **********************************************************************
  711.  
  712. _SysBase    dc.l    0
  713. _DOSBase    dc.l    0
  714.  
  715.     IFGT    ASTART
  716. _WBenchMsg    dc.l    0
  717. _stdin        dc.l    0
  718. _stdout        dc.l    0
  719. _stderr        dc.l    0
  720. _errno        dc.l    0
  721.     ENDC    ASTART
  722.  
  723.     IFGT    DEBUG
  724. initialSP    dc.l    0
  725. dosCmdLen    dc.l    0
  726. dosCmdBuf    dc.l    0
  727.     ENDC    DEBUG
  728.  
  729. VerRev        dc.w    34,12
  730.     IFGT    ASTART
  731.         dc.b    'A'
  732.     ENDC    ASTART
  733.     IFEQ    ASTART
  734.         dc.b    'R'
  735.     ENDC    ASTART
  736.     IFGT    WINDOW
  737. _NeedWStartup:
  738.         dc.b    'W'
  739.     ENDC    WINDOW
  740.     IFEQ    WBOUT
  741.         dc.b    'X'
  742.     ENDC    WBOUT
  743.     IFGT    NARGS
  744.         dc.b    'N'
  745.     ENDC    NARGS
  746.     IFGT    DEBUG
  747.         dc.b    'D'
  748.     ENDC    DEBUG
  749.     IFGT    QARG
  750.         dc.b    'Q'
  751.     ENDC    QARG
  752.  
  753.     END
  754.  
  755.